package datatypes;


public class SuperMarket {

	private TLista productos;

	public SuperMarket() {
		this.productos = new TLista();
	}

	public TLista getProductos() {
		return productos;
	}

	public void setProductos(TLista productos) {
		this.productos = productos;
	}

	/**
	 * Este metodo me asegura que la etiqueta del elemento (TElemento) de la
	 * lista es el mismo que el nombre del producto que se inserta lo cual
	 * facilita la busqueda de los productos luego. Tambien se inserta el
	 * producto con el insertarOrdenado() lo cual asegura que cuando se imprimen
	 * los productos van a estar ordenados por nombre (si es que el insertar
	 * ordenado anda bien).
	 * 
	 * @param producto
	 *            El producto a agregar
	 * @return
	 */
	public Respuesta agregarProducto(Producto producto) {
		if (producto != null && productos != null) {
			if (!existeProducto(producto)) {
				IElemento elemento = new TElemento();
				elemento.setEtiqueta(producto.getName());
				elemento.setDato(producto);
				return new Respuesta(productos.insertarOrdenado(elemento),
						"El elemento fue insertado correctamente");
			} else {
				return new Respuesta(false,
						"El nombre del elemento o el codigo ya existian");
			}
		}
		return new Respuesta(false, "No se pudo insertar el elemento");
	}

	/**
	 * Este metodo sirve para aumentar el stock de un producto.
	 * 
	 * @param nombreProducto
	 *            : el producto al que se le quiere aumentar el stock
	 * @param cantidad
	 *            : la cantidad por la cual sele quiere aumentar.
	 * @return
	 */
	public Respuesta agregarStock(String nombreProducto, Integer cantidad) {
		/*
		 * me fijo que el producto que le paso no es nulo y que el producto esta
		 * en el supermercado
		 */
		if (nombreProducto != null
				&& productos.buscarElemento(nombreProducto) != null) {
			/*
			 * busco el producto y lo referencio en una variable (el dato del
			 * elemento es el producto y la etiqueta del elemento concide con el
			 * nombre del producto)
			 */
			Producto p = (Producto) productos.buscarElemento(nombreProducto)
					.getDato();
			/*
			 * seteo el stock de dicho producto como la cantidad que ya tenia el
			 * stock mas la cantidad que se le queria agregar al stock
			 */
			p.setStock(p.getStock() + cantidad);
			return new Respuesta(true, "El stock del producto se aumento en "
					+ cantidad);
		}

		return new Respuesta(false, "El producto no existe");
	}

	/**
	 * Este metodo simula la venta de un producto reduciendo su stock en la
	 * cantidad de productos vendidos.
	 * 
	 * @param nombreProducto
	 *            el nombre del producto que se va a vender.
	 * @param cantidadVendida
	 *            la cantidad del producto que se va a vender
	 * @return
	 */
	public Respuesta venderProducto(String nombreProducto,
			Integer cantidadVendida) {
		/*
		 * me fijo que el producto que le paso no es nulo y que el producto esta
		 * en el supermercado
		 */
		if (nombreProducto != null
				&& productos.buscarElemento(nombreProducto) != null) {
			/* agarro el producto */

			Producto prod = (Producto) productos.buscarElemento(nombreProducto)
					.getDato();

			if (prod.getStock() >= cantidadVendida) {
				prod.setStock(prod.getStock() - cantidadVendida);
				return new Respuesta(true,
						"Se vendieron correctamente y el stock ahora es de "
								+ prod.getStock().toString());
			} else 
				if (prod.getStock()>0){
				Integer vendidos = prod.getStock();
				Integer noVendidos = cantidadVendida - prod.getStock();
				prod.setStock(0);
				return new Respuesta(true, "Se vendieron "
						+ vendidos.toString()
						+ " unidades pero no se pudueron vender " + noVendidos + " y el stock esta vacio.");
			}else{
				return new Respuesta(false,"No hay stock del producto.");
			}
		}
		return new Respuesta(false, "El producto no existe.");
	}

	/**
	 * Metodo que elimina un producto de la lista del supermercado y tambien su
	 * stock.
	 * 
	 * @param nombreProducto
	 * @return
	 */
	public Boolean eliminarProducto(String nombreProducto) {
		if (nombreProducto != null
				&& productos.buscarElemento(nombreProducto) != null) {
			return productos.eliminarElemento(nombreProducto);
		}
		return false;
	}

	/**
	 * metodo que retorna el precio de un producto dado su codigo
	 * 
	 * @param codigo
	 * @return
	 */

	public Double leerCodigo(Integer codigo) {
		if (codigo != null) {
			IElemento aux = productos.getPrimero();
			while (aux != null) {
				if (((Producto) aux.getDato()).getCode().equals(codigo)) {
					Producto p = (Producto) aux.getDato();
					if (p.getStock() > 1) {
						venderProducto(p.getName(), 1);
						return p.getPrice();
					}

				}
				aux = aux.getSiguiente();
			}
		}
		return null;
	}

	/**
	 * metodo que lee una lista de codigos y retorna el valor acumulado de los
	 * mismos
	 * 
	 * @param lista
	 * @return
	 */
	public Double leerProductosEnCaja(TLista lista) {
		if (lista != null && !lista.esVacia()) {
			IElemento aux = lista.getPrimero();
			Double importeTotal = 0.0;
			while (aux != null) {
				Producto prod = (Producto) aux.getDato();
				importeTotal = importeTotal
						+ leerCodigo(prod.getCode());
				aux = aux.getSiguiente();
			}
			return importeTotal;
		}
		return null;
	}

	/**
	 * metodo que revisa si el nombre o el codigo del producto ya existe
	 * 
	 * @param prod
	 * @return
	 */
	public Boolean existeProducto(Producto prod) {
		if (!productos.esVacia()) {
			IElemento elem = productos.getPrimero();
			while (elem != null) {
				Producto producto = (Producto) elem.getDato();
				if (prod.getName().compareTo(producto.getName()) == 0
						|| prod.getCode().compareTo(producto.getCode()) == 0) {
					return true;
				}
				elem = elem.getSiguiente();
			}

		}
		return false;
	}
	
	/**
	 * Metodo encargado de fusionar el stock del supermercado actual con uno dado
	 * @param productos
	 * @return
	 */
	public Boolean fusionarStocks(TLista productos){
		if (productos.esVacia()|| productos==null){
			return false;
		}
		IElemento elem = productos.getPrimero();
		Producto prod = (Producto) elem.getDato();
		while(elem!= null){
			if(this.existeProducto(prod)){
				this.agregarStock(prod.getName(), prod.getStock());
			}
			else{
				this.agregarProducto(prod);
			}
			elem = elem.getSiguiente();
		}
		return true;
	}
	
	
	/**
	 * Retorna string de etiquetas de productos
	 * @return
	 */
	public String[] devolverEtiquetas(){
		if (this.getProductos().esVacia()) {
			String[] com = new String[0];
			return com;
		} else {
			int i = this.getProductos().obtenerCantidadElementos();
			String[] comp = new String[i];
			i = 0;
			IElemento temp = this.getProductos().getPrimero();
			while (temp != null) {
				comp[i] = temp.getEtiqueta();
				i++;
				temp = temp.getSiguiente();
			}
			return comp;
		}
	}
}
